package chatclient;

import model.GalaxyConnection;
import controller.Communicate;
import java.awt.Frame;
import java.awt.event.KeyEvent;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import model.Constantes;
import model.DataMssge;
import model.User;

/**
 *
 * @author carlos
 */
public class ChatClient extends javax.swing.JFrame {

    // Method variables
    public static GalaxyConnection connClient;
    public FCrearCuenta fCuenta = null;
    public FChat fChat = null;
    private Socket socketClient = null;
    private Communicate comm = null;
    private User currentUser = null;
    private static Properties configFile;

    public User getCurrentUser() {
        return currentUser;
    }

    public void setCurrentUser(User currentUser) {
        this.currentUser = currentUser;
    }

    public Socket getSocketClient() {
        return socketClient;
    }

    public Communicate getComm() {
        return comm;
    }

    /**
     * Creates new form ChatClient
     */
    public ChatClient() throws FileNotFoundException {
        InputStream isProperties = null;

        initComponents();

        //read the properties file
        String strFilename1 = "ichat.properties";
        String strFilename2 = "build\\classes\\ichat.properties";

        if (new java.io.File(strFilename1).isFile()) {
            //execution from jar file
            isProperties = new java.io.FileInputStream(strFilename1);
        } else if (new java.io.File(strFilename2).isFile()) {
            //execution from class files
            isProperties = ChatClient.class.getResourceAsStream("..\\" + strFilename1);
        } else {
            System.out.println("cannot find ichat.properties file");
            dispose();
            System.exit(0);
        }
        configFile = new Properties();

        try {
            configFile.load(isProperties);
        } catch (IOException ex) {
            Logger.getLogger(ChatClient.class.getName()).log(Level.SEVERE, null, ex);
            dispose();
            System.exit(-1);
        } catch (NullPointerException ex) {
            Logger.getLogger(ChatClient.class.getName()).log(Level.SEVERE, null, ex);
            dispose();
            System.exit(-1);
        }

        connClient = new GalaxyConnection();

        connClient.setConnServer(configFile.getProperty(Constantes.CONN_IP));
        connClient.setConnPort(Integer.parseInt(configFile.getProperty(Constantes.CONN_PORT)));
        connClient.setConnAutoLogin(Boolean.parseBoolean(configFile.getProperty(Constantes.CONN_AUTOLOGIN)));

        //get the user and password if the login is automatic
        if (connClient.isConnAutoLogin()) {
            connClient.setConnUser(configFile.getProperty(Constantes.CONN_DEFAULT_USER));
            connClient.setConnPasswd(configFile.getProperty(Constantes.CONN_DEFAULT_PASSWD));
        }

        initializeErrorIcons();
        comm = new Communicate();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        lblPassword = new javax.swing.JLabel();
        txtUsername = new javax.swing.JTextField();
        lblUsername = new javax.swing.JLabel();
        cmdConnect = new javax.swing.JButton();
        cmdCreateAccount = new javax.swing.JButton();
        lblErrorMessage = new javax.swing.JLabel();
        lblTitle = new javax.swing.JLabel();
        lblIconUsername = new javax.swing.JLabel();
        lblIconPasswd = new javax.swing.JLabel();
        txtPassword = new javax.swing.JPasswordField();
        jLabel1 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Chat Galaxy - Login");
        setBackground(new java.awt.Color(204, 204, 204));
        setLocationByPlatform(true);
        setMinimumSize(new java.awt.Dimension(251, 218));
        setModalExclusionType(null);
        setPreferredSize(new java.awt.Dimension(290, 260));
        setResizable(false);
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });
        getContentPane().setLayout(null);

        lblPassword.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        lblPassword.setText("Password: ");
        getContentPane().add(lblPassword);
        lblPassword.setBounds(10, 110, 80, 20);
        getContentPane().add(txtUsername);
        txtUsername.setBounds(90, 70, 140, 30);

        lblUsername.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        lblUsername.setText("Username:");
        getContentPane().add(lblUsername);
        lblUsername.setBounds(11, 73, 80, 20);

        cmdConnect.setText("sign in");
        cmdConnect.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cmdConnectActionPerformed(evt);
            }
        });
        getContentPane().add(cmdConnect);
        cmdConnect.setBounds(110, 160, 80, 40);

        cmdCreateAccount.setText("create account");
        cmdCreateAccount.setBorderPainted(false);
        cmdCreateAccount.setOpaque(false);
        cmdCreateAccount.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cmdCreateAccountActionPerformed(evt);
            }
        });
        getContentPane().add(cmdCreateAccount);
        cmdCreateAccount.setBounds(90, 210, 120, 15);

        lblErrorMessage.setForeground(new java.awt.Color(204, 0, 51));
        lblErrorMessage.setName("lblErrorMessage");
        getContentPane().add(lblErrorMessage);
        lblErrorMessage.setBounds(60, 40, 205, 17);

        lblTitle.setFont(new java.awt.Font("Lucida Calligraphy", 1, 18)); // NOI18N
        lblTitle.setForeground(new java.awt.Color(255, 255, 255));
        lblTitle.setText("Welcome to Chat-Galaxy");
        getContentPane().add(lblTitle);
        lblTitle.setBounds(10, 10, 280, 30);

        lblIconUsername.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tools/notification_error.png"))); // NOI18N
        getContentPane().add(lblIconUsername);
        lblIconUsername.setBounds(240, 80, 16, 16);

        lblIconPasswd.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tools/notification_error.png"))); // NOI18N
        getContentPane().add(lblIconPasswd);
        lblIconPasswd.setBounds(240, 120, 16, 16);

        txtPassword.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                txtPasswordKeyReleased(evt);
            }
        });
        getContentPane().add(txtPassword);
        txtPassword.setBounds(90, 110, 140, 30);

        jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tools/backgroundWelcomeFrame.png"))); // NOI18N
        getContentPane().add(jLabel1);
        jLabel1.setBounds(0, -20, 330, 250);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void cmdConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmdConnectActionPerformed
        signIn();
    }//GEN-LAST:event_cmdConnectActionPerformed

    private void cmdCreateAccountActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmdCreateAccountActionPerformed
        try {
            //creates a new communication socket
            initServerCommunication();

            //opens new form to create a new account
            this.setEnabled(false);
            this.fCuenta = new FCrearCuenta(this);
            Common.centerFrame(this.fCuenta);
            this.fCuenta.setVisible(true);
        } catch (UnknownHostException ex) {
            Common.ErrorMessage("Error de conexion: " + ex.getMessage(), ex);
        } catch (IOException ex) {
            Common.ErrorMessage("Error de conexion: " + ex.getMessage(), ex);
        }
    }//GEN-LAST:event_cmdCreateAccountActionPerformed

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        try {
            if (this.getSocketClient() != null && !this.getSocketClient().isClosed()) {
                getSocketClient().close();
            }
        } catch (IOException ex) {
            Common.ErrorMessage("Error grave al cerrar el Socket: " + ex.getMessage(), ex);
        }
    }//GEN-LAST:event_formWindowClosing

    private void txtPasswordKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtPasswordKeyReleased
        int key = evt.getKeyCode();
        switch (key) {
            case KeyEvent.VK_ENTER:
                signIn();
                break;
            default:
                break;
        }
    }//GEN-LAST:event_txtPasswordKeyReleased

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            Common.ErrorMessage("Error de inicializacion del formulario: " + ex.getMessage(), ex);
        } catch (InstantiationException ex) {
            Common.ErrorMessage("Error de inicializacion del formulario: " + ex.getMessage(), ex);
        } catch (IllegalAccessException ex) {
            Common.ErrorMessage("Error de inicializacion del formulario: " + ex.getMessage(), ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            Common.ErrorMessage("Error de inicializacion del formulario: " + ex.getMessage(), ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException ex) {
                    Logger.getLogger(ChatClient.class.getName()).log(Level.SEVERE, null, ex);
                }

                ChatClient fCliente = null;
                try {
                    fCliente = new ChatClient();
                } catch (FileNotFoundException ex) {
                    //this exception will never occur, because it is checked if the file is found
                    Logger.getLogger(ChatClient.class.getName()).log(Level.SEVERE, null, ex);
                }
                
                Common.centerFrame(fCliente);
                fCliente.setVisible(true);

                //check if logon is automatic
                if (connClient.isConnAutoLogin()) {
                    fCliente.txtUsername.setText(connClient.getConnUser());
                    fCliente.txtPassword.setText(connClient.getConnPasswd());
                    fCliente.signIn();
                }
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton cmdConnect;
    private javax.swing.JButton cmdCreateAccount;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel lblErrorMessage;
    private javax.swing.JLabel lblIconPasswd;
    private javax.swing.JLabel lblIconUsername;
    private javax.swing.JLabel lblPassword;
    private javax.swing.JLabel lblTitle;
    private javax.swing.JLabel lblUsername;
    private javax.swing.JPasswordField txtPassword;
    private javax.swing.JTextField txtUsername;
    // End of variables declaration//GEN-END:variables

    public void initServerCommunication() throws UnknownHostException, IOException {
        if (this.getSocketClient() == null || this.getSocketClient().isClosed() == true) {
            // creates the socket
            this.socketClient = new Socket(connClient.getConnServer(), connClient.getConnPort());

            //Sets the objects for writing to the socket
            comm.setSocketConnection(this.getSocketClient());

            // creates a new thread to listen for responses
            ResponseProcess rp = new ResponseProcess(this);
            Thread t = new Thread(rp);
            t.start();
        }
    }

    void ConnectionClosed() {
        if (this.fCuenta != null) {
            this.fCuenta.dispose();
        }
        if (this.fChat != null) {
            this.fChat.dispose();
        }

        try {
            comm.closeConnectionObjects();
        } catch (IOException ex) {
            Common.ErrorMessage("Error al cerrar objetos de escritura en socket: " + ex.getMessage(), ex);
        }

        this.setVisible(true);
        this.setEnabled(true);
        this.lblErrorMessage.setText("Conexion terminada.");
    }

    void OpenChat(DataMssge datos) {
        //closes fcuenta if opened
        if (this.fCuenta != null) {
            this.fCuenta.setVisible(false);
            this.fCuenta.dispose();
        }

        //hides the current form
        this.setEnabled(false);
        this.setVisible(false);

        //opens the chat form
        this.fChat = new FChat(this);
        Common.centerFrame(this.fChat);
        this.fChat.setVisible(true);

        this.currentUser = datos.getUser();
        this.fChat.refreshUCList(datos);
        this.fChat.setUserNameDisplay(this.currentUser.getUsername());
                
        //minimize window if auto login
        if (connClient.isConnAutoLogin()) {
            this.fChat.setState(Frame.ICONIFIED);
        }
    }

    //initializes all Error icons to invisible
    private void initializeErrorIcons() {
        lblIconUsername.setVisible(false);
        lblIconPasswd.setVisible(false);
    }

    void WriteResponseError(DataMssge datos) {
        switch (datos.getOption()) {
            case crearcuenta:
                this.fCuenta.setErrorLabel(datos.getStrError());
                break;
            case conectarse:
                this.lblErrorMessage.setText(datos.getStrError());
                break;
            default:
        }
    }

    void showParent() {
        this.setEnabled(true);
        this.toFront();
    }

    private void signIn() {
        DataMssge datos = new DataMssge();
        boolean blnHasErrors = false;

        initializeErrorIcons();

        // Check inserted data
        if (!ValidationMethods.isUserValid(txtUsername.getText())) {
            blnHasErrors = true;
            lblIconUsername.setVisible(true);

        }
        // Check inserted data
        if (!ValidationMethods.isPasswordValid(txtPassword.getText())) {
            blnHasErrors = true;
            lblIconPasswd.setVisible(true);
        }

        if (!blnHasErrors) {
            datos.setOption(Constantes.Eoption.conectarse);
            datos.getUser().setUsername(txtUsername.getText());
            datos.getUser().setPassword(txtPassword.getText());

            try {
                //creates a new communication socket
                initServerCommunication();
                comm.sendRequest(datos);

            } catch (IOException ex) {
                Common.ErrorMessage("Error al mandar peticion: " + ex.getMessage(), ex);
            }
        }
    }
}
